<?php
/**
 * @link https://ym2.cleverstone.top
 * @copyright Copyright (c) 2020 Yii Manager Software LLC
 */

namespace backend\controllers;

use builder\base\BaseController;
use builder\form\FormBuilder;
use builder\helper\H5;
use builder\helper\T;
use builder\tree\TreeBuilder;
use common\models\Admin;
use common\models\SystemAuthRelation;
use common\models\SystemGroup;
use common\models\SystemGroupService;

/**
 * 管理组
 * @author cleverstone
 * @since ym2.0
 */
class GroupController extends BaseController
{
    public $actionVerbs = [
        'index' => ['GET'],
        'create' => ['GET', 'POST'],
        'update' => ['GET', 'POST'],
        'delete' => ['POST'],
        'dispatch' => ['GET', 'POST'],
    ];

    /**
     * 管理组列表
     * @return string
     * @throws \builder\base\InvalidInstanceException
     * @throws \builder\base\NotFoundParamsException
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function actionIndex()
    {
        $viewBuilder = $this->viewBuilder;

        $treeTable = $viewBuilder->getTreeTable(['id' => 'group_index']);
        if ($this->isAjax) {
            $treeTable->setPage(false)
                ->setQuery(function () {
                    return SystemGroupService::tree();
                })
                ->setTtColumns([
                    'id',
                    'name',
                    'desc' => function ($row) {
                        return $row['desc'] ?: '-';
                    },
                    'status' => function ($row) {
                        return H5::badge($row['status'] ? '正常' : '禁用', $row['status'] ? 'primary' : 'red');
                    },
                    'created_at',
                    'updated_at',
                ]);

        } else {
            $treeTable->setTitle('管理组列表')
                ->setPage(false)
                ->setMaxHeight(800)
                ->setTreeTableHead([
                    $this->treeTableHead->field('id')->title('ID'),
                    $this->treeTableHead->field('name')->title('管理组')->minWidth(300),
                    $this->treeTableHead->field('desc')->title('注释')->width(300),
                    $this->treeTableHead->field('status')->title('状态')->width(100),
                    $this->treeTableHead->field('created_at')->title('添加时间')->width(180),
                    $this->treeTableHead->field('updated_at')->title('上次更新')->width(180),
                    $this->treeTableHead->toolbar()->title('操作项')->width(250),
                ])
                ->setTreeViewOption([
                    'expandAllDefault' => true,
                ])
                ->setTtRowOperation([
                    $this->ttRowOperation->modal()->title('权限')->route('group/dispatch'),
                    $this->ttRowOperation->modal()->title('添加子组')->route('group/create')->height(430),
                    $this->ttRowOperation->modal()->title('编辑')->route('group/update')->height(515),
                    $this->ttRowOperation->ajax()->title('删除')->route('group/delete')->method('POST'),
                ])
                ->setTtToolbarCustom([
                    $this->ttToolbarCustom->modal()->btnClass('btn-primary')->title('新增')->route('group/create')->height(430),
                ])
                ->setTtToolbarExpandAll();
        }

        return $viewBuilder->render();
    }

    /**
     * 新增
     * @param null|int $id 管理组ID
     * @return string
     * @throws \Throwable
     */
    public function actionCreate($id = null)
    {
        if ($this->isPost) {
            $bodyParams = $this->filteredPost;
            $model = new SystemGroup();
            $model->setScenario('group_add');
            $model->load($bodyParams);
            if ($model->pid) {
                $parentModel = SystemGroup::findOne($model->pid);
                $model->path = $parentModel->path . $parentModel->id . '-';
            } else {
                $model->path = '-0-';
            }
            if ($model->save()) {
                return $this->asOk("新增管理组【{$model->name}】成功");
            }

            return $this->asFail($model->error);
        } else {
            return FormBuilder::instance(['id' => 'group_create'])
                ->setTitle('新增')
                ->setPartial()
                ->setRequiredStyle()
                ->setFormControl([
                    'pid' => $this->formControl->hidden()->defaultValue($id ?: 0),
                    'name' => $this->formControl->text()->label('组名')->required()->placeholder('请填写管理组名'),
                    'desc' => $this->formControl->textarea()->label('注释'),
                    'status' => $this->formControl->sw()->label('状态')->required()->title('启用', '禁用')->checked(),
                ])
                ->setAutoClose()
                ->setSubmittedCalls(['parent' => ['group_index']])
                ->setCloseBtn()
                ->setSubmitBtn()
                ->render();
        }
    }

    /**
     * 编辑
     * @param int $id 管理组ID
     * @return string
     * @throws \Throwable
     */
    public function actionUpdate($id)
    {
        $model = SystemGroup::findOne($id);
        if ($this->isPost) {
            if (empty($model)) {
                return $this->asFail("ID:【{$id}】错误, 数据不存在");
            }

            $bodyParams = $this->filteredPost;
            $model->setScenario('group_update');
            $model->load($bodyParams);
            if (!$model->validate()) {
                return $this->asFail($model->error);
            }
            if ($model->pid == $model->id) {
                return $this->asFail('选择的父分组不能是自身');
            }

            if ($model->pid) {
                $parentGroup = SystemGroup::findOne($model->pid);
                $model->path = $parentGroup->path . $parentGroup->id . '-';
            } else {
                $model->path = '-0-';
            }

            $model->save(false);
            return $this->asOk("编辑管理组【{$model->name}】成功");
        } else {
            if (empty($model)) {
                return $this->renderContentX(H5::alert('ID错误,数据不存在'), 'error');
            }

            $groupTree = SystemGroupService::tree();
            array_unshift($groupTree, [
                'id' => 0,
                'name' => '顶级分组',
                'children' => [],
            ]);
            return FormBuilder::instance(['id' => 'group_update'])
                ->setTitle('编辑')
                ->setPartial()
                ->setRequiredStyle()
                ->setFormControl([
                    'pid' => $this->formControl->xselectTree()
                        ->label('父分组')
                        ->tips('请选择父分组')
                        ->radio()
                        ->strict(false)
                        ->filterable()
                        ->clickClose()
                        ->expandedKeys(true)
                        ->required()
                        ->defaultValue($model->pid)
                        ->data($groupTree)
                        ->addPluginOption('prop', [
                            'value' => 'id',
                        ]),
                    'name' => $this->formControl->text()->label('组名')->required()->placeholder('请填写管理组名')->defaultValue($model->name),
                    'desc' => $this->formControl->textarea()->label('注释')->defaultValue($model->desc),
                    'status' => $this->formControl->sw()->label('状态')->required()->title('启用', '禁用')->checked(!!$model->status),
                ])
                ->setAutoClose()
                ->setSubmittedCalls(['parent' => ['group_index']])
                ->setCloseBtn()
                ->setSubmitBtn()
                ->render();
        }
    }

    /**
     * 删除
     * @return string
     * @throws \Throwable
     * @throws \yii\db\StaleObjectException
     */
    public function actionDelete()
    {
        $bodyParams = $this->filteredPost;
        if (empty($bodyParams['id'])) {
            return $this->asOk('参数ID缺失');
        }
        $id = $bodyParams['id'];
        $model = SystemGroup::findOne($id);
        if (empty($model)) {
            return $this->asFail("ID:【{$id}】错误, 数据不存在");
        }
        $children = SystemGroup::query()->where(['like', 'path', "-{$id}-"])->one();
        if (!empty($children)) {
            return $this->asFail('请删除子分组后, 重新操作');
        }

        $user = Admin::findOne(['group' => $id]);
        if (!empty($user)) {
            return $this->asFail("管理组【{$model->name}】存在账号占用, 无法删除");
        }

        $model->delete();
        return $this->asOk("删除管理组【{$model->name}】成功");
    }

    /**
     * 权限
     * @param int $id 管理组ID
     * @return string
     * @throws \Throwable
     */
    public function actionDispatch($id)
    {
        $groupModel = SystemGroup::findOne($id);
        if ($this->isPost) {
            $bodyParams = $this->filteredPost;
            if (empty($bodyParams['id'])) {
                return $this->asFail('参数ID缺失');
            }
            $menuIds = $bodyParams['id'];

            $trans = $this->db->beginTransaction();
            try {
                //delete
                SystemAuthRelation::deleteAll(['group_id' => $id]);
                //create
                $tmp = [];
                $now = T::now();
                foreach ($menuIds as $mid) {
                    if ($mid && !in_array($mid, $tmp)) {
                        $tmp[] = [$id, $mid, $now];
                    }
                }

                $this->db->createCommand()->batchInsert(
                    SystemAuthRelation::tableName(),
                    ['group_id', 'menu_id', 'created_at'],
                    $tmp
                )->execute();

                $trans->commit();

                \Yii::$app->rbacManager->invalidateCachePermissions($id);

                return $this->asOk("管理组【{$groupModel->name}】分配权限成功");
            } catch (\Exception $e) {
                $trans->rollBack();
                return $this->asFail($e->getMessage());
            }
        } else {
            $tree = TreeBuilder::instance(['id' => 'group_dispatch']);
            if ($this->isAjax) {
                $tree->setData(function () use ($groupModel) {
                    return SystemAuthRelation::permissionTree($groupModel->id, $groupModel->pid);
                });
            } else {
                $extraCss = <<<'CSS'
                .btn-bottom-group{text-align:right;}
CSS;
                $tree->setTitle('权限')
                    ->setPartial()
                    ->setTreeLayout([
                        'class' => ['h-550', 'overflow-auto'],
                    ])
                    ->setExtraCss($extraCss)
                    ->setCustomName([
                        'title' => 'name',
                    ])
                    ->setSwitchCheckedBtn()
                    ->setSwitchSpreadBtn()
                    ->setOperationItem([
                        $this->operationItem->ajax()
                            ->positionBottom()
                            ->title('立即提交')
                            ->params(['id'])
                            ->closeModal()
                            ->questionDescription('确认当前权限分配吗?')
                            ->method(),
                    ]);
            }

            return $tree->render();
        }
    }
}